﻿namespace Minesweeper
{
    using System;
    using System.IO;
    using System.Threading;

    public class MinesweeperGame
    {
        public static Random RandomGenerator = new Random();
        private static LevelHandler levelHandler = new LevelHandler();
        private static Level defaultLevel = Level.Beginner;
        public static string playerName;
        public static int seconds = -1;
        private static int oldSecond = 0;
        private static bool firstTurn = true;
        private static int startTimer = Timeout.Infinite;
        public static Timer timer;
        public static uint FontIndex = 9;
        public static bool NewGame = true;
        public static Level ChosenLevel = Level.Beginner;

        public static MineField playField = null;

        static int rightBorder;
        static int bottomBorder;
        static int currentCursorX = 0;
        static int currentCursorY = 0;

        private static void SetConsoleSizeAndBorders()
        {
            Console.Clear();
            Console.SetWindowSize((playField.Width * 4) + 30, (playField.Height * 6) + 2);
            Console.SetBufferSize((playField.Width * 4) + 30, (playField.Height * 6) + 2);
            rightBorder = playField.Width * 3 + playField.Width + 1;
            bottomBorder = playField.Height * 5 + playField.Height + 1;
        }

        private static bool CheckForWin()
        {
            bool win = false;
            int numberOfEmptyCells = 0;
            for (int row = 0; row < playField.Height; row++)
            {
                for (int cow = 0; cow < playField.Width; cow++)
                {
                    if (playField[row, cow].IsVisited)
                    {
                        numberOfEmptyCells++;
                    }
                }
            }

            if (numberOfEmptyCells == (playField.Width * playField.Height) - playField.NumberOfMines)
            {
                win = true;
            }
            return win;
        }

        public static bool ContinueGame(int posY)
        {
            bool wishToContinue = false;
            string question = "Do you wish to continue?";
            int posX = (Console.WindowWidth / 2) - (question.Length / 2);
            posY++;
            Console.SetCursorPosition(posX, posY);
            Console.Write(question);
            question = "Y/N";
            posY++;
            posX = (Console.WindowWidth / 2) - (question.Length / 2);
            Console.SetCursorPosition(posX, posY);
            Console.Write(question);
            ConsoleKeyInfo key = Console.ReadKey();
            if (key.Key == ConsoleKey.Y)
            {
                wishToContinue = true;
            }

            return wishToContinue;
        }

        private static void ReadAndProcessEnterKeys()
        {
            ConsoleKeyInfo pressedKey = Console.ReadKey(true);

            while (Console.KeyAvailable) Console.ReadKey(true);

            if (pressedKey.Key == ConsoleKey.LeftArrow)
            {
                ConsoleDrawer.UnHighLightCell(currentCursorX, currentCursorY);
                if (currentCursorX - (Cell.CellWidth + 1) >= 0)
                {
                    currentCursorX -= (Cell.CellWidth + 1);
                    playField.CurrentCol--;
                }
                ConsoleDrawer.HighlightCell(currentCursorX, currentCursorY);
            }
            else if (pressedKey.Key == ConsoleKey.RightArrow)
            {
                ConsoleDrawer.UnHighLightCell(currentCursorX, currentCursorY);
                if (currentCursorX + 2 * (Cell.CellWidth + 1) < rightBorder)
                {
                    currentCursorX += (Cell.CellWidth + 1);
                    playField.CurrentCol++;
                }
                ConsoleDrawer.HighlightCell(currentCursorX, currentCursorY);
            }
            else if (pressedKey.Key == ConsoleKey.DownArrow)
            {
                ConsoleDrawer.UnHighLightCell(currentCursorX, currentCursorY);
                if (currentCursorY + 2 * (Cell.CellHeight + 1) < bottomBorder)
                {
                    currentCursorY += (Cell.CellHeight + 1);
                    playField.CurrentRow++;
                }
                ConsoleDrawer.HighlightCell(currentCursorX, currentCursorY);
            }
            else if (pressedKey.Key == ConsoleKey.UpArrow)
            {
                ConsoleDrawer.UnHighLightCell(currentCursorX, currentCursorY);
                if (currentCursorY - (Cell.CellHeight + 1) >= 0)
                {
                    currentCursorY -= (Cell.CellHeight + 1);
                    playField.CurrentRow--;
                }
                ConsoleDrawer.HighlightCell(currentCursorX, currentCursorY);
            }
            else if (pressedKey.Key == ConsoleKey.Enter)
            {
                if (firstTurn)
                {
                    playField.PlaceMines();
                    playField.FillGameBoard();
                    firstTurn = false;
                }

                ConsoleDrawer.OpenCell(currentCursorX, currentCursorY);
                if (CheckForWin())
                {
                    ConsoleDrawer.WinGame();
                }

            }
            else if (pressedKey.Key == ConsoleKey.Spacebar) //Space for putting flags
            {
                if (firstTurn)
                {
                    playField.PlaceMines();
                    playField.FillGameBoard();
                    firstTurn = false;
                }

                ConsoleDrawer.PlaceOrRemoveFlag(currentCursorX, currentCursorY);
            }
        }

        public static void Main()
        {
            if (NewGame)
            {
                Menu.SelectMenu();
            }

            if (playField == null)
            {
                playField = Menu.CreatePlayField(defaultLevel);
            }

            ConsoleExtender.ConsoleHelper.SetConsoleFont(0);
            SetConsoleSizeAndBorders();
            playField.InitialDraw();

            Console.SetCursorPosition(currentCursorX, currentCursorY);
            firstTurn = true;
            while (true)
            {
                timer = new Timer(TimerCallback, null, startTimer, 1000);
                Thread.Sleep(1); // Fixes some bugs
                ReadAndProcessEnterKeys();
                startTimer = 0;
            }
        }

        public static void TimerCallback(Object o)
        {
            int posX = (playField.Width * 4) + 5;
            int posY = 3;

            Console.BackgroundColor = ConsoleColor.Black;
            if (DateTime.Now.Second != oldSecond)
            {
                oldSecond = DateTime.Now.Second;
                seconds++;
            }
            TimeDigits.DrawTimeBox((playField.Width * 4) + 2, 1);
            TimeDigits.DrawTimeDigit(posX, posY, (seconds / 10000) % 10);
            posX += 4;
            TimeDigits.DrawTimeDigit(posX, posY, (seconds / 1000) % 10);
            posX += 4;
            TimeDigits.DrawTimeDigit(posX, posY, (seconds / 100) % 10);
            posX += 4;
            TimeDigits.DrawTimeDigit(posX, posY, (seconds / 10) % 10);
            posX += 4;
            TimeDigits.DrawTimeDigit(posX, posY, seconds % 10);
            GC.Collect();
        }

        public static void ResetGameStatusAndContinue()
        {
            levelHandler = new LevelHandler();
            defaultLevel = ChosenLevel;

            playerName = string.Empty;
            seconds = -1;
            oldSecond = 0;
            firstTurn = true;
            startTimer = Timeout.Infinite;
            timer = null;

            playField = null;

            rightBorder = 0;
            bottomBorder = 0;
            currentCursorX = 0;
            currentCursorY = 0;

            Main();
        }
    }
}
